home *** CD-ROM | disk | FTP | other *** search
Korn shell script | 1997-08-26 | 8.0 KB | 270 lines |
- #!/bin/ksh
- # @(#) p.ksh 1.2 97/06/26
- # p: page compressed & plain files in the order given
- # 92/01/23 john h. dubois iii (john@armory.com)
- # 92/02/14 changed incorrect zpack to pcat
- # 92/02/16 added help
- # 92/10/11 search for file.Z and file.z if file not found
- # 92/10/18 pass options to pager
- # 93/11/09 Understand gzipped files too
- # Wait after printing message about unreadable files
- # Make less prompt include name of file being uncompressed
- # 95/08/05 Added -<num> option
- # 96/10/27 Make -s required for strings option. Added m option.
- # 96/12/16 Made options be passed correctly to pager again.
- # 96/12/19 Use LESSOPEN if pager is less
- # 97/06/26 Added v option.
-
- # Usage: PageInput exec filename pager-options
- # Page the standard input. If filename is non-null and the pager is less,
- # the filename is put in the prompt. exec should be either null, or the
- # word "exec" to cause the pager to be exec'd. pager-options are passed to
- # the pager.
- function PageInput {
- typeset exec=$1 filename=$2 Opts=$3
-
- # If pager is less, set the prompt to include the name of
- # the file being uncompressed. Escape dots in the extension
- # because less treats . specially in prompts.
- if [[ "$PAGER" = *less && -n "$filename" ]]; then
- fsub . "\." "$filename"
- $exec $PAGER "-P[$fsub_ret] (%pb\\%)" $Opts
- else
- $exec $PAGER $Opts
- fi
- }
-
- # Usage: Page filename pager-options input-file ...
- # No input-file indicates that the standard input should be paged.
- # filename is used to pass a filename (if there is one available) that the
- # standard input is coming from, so that it can be put in a prompt for less.
- # If the global stringsCmd is not null, each input file is run through it.
- # If the global "exec" is set to exec, the pager is exec'ed. If stringsCmd
- # is set, it is exec'ed for the last file.
- function Page {
- typeset filename=$1 Opts=$2 file
-
- shift 2
-
- if [ $# -eq 0 ]; then # Page input
- [ -n "$stringsCmd" ] &&
- $stringsCmd | PageInput "$exec" "$filename" "$Opts" ||
- PageInput "$exec" "$filename" "$Opts"
- elif [ -n "$stringsCmd" ]; then
- while [ $# -gt 1 ]; do
- $stringsCmd < "$1" | PageInput "" "$1" "$Opts"
- shift
- done
- $stringsCmd < "$1" | PageInput "$exec" "$1" "$Opts"
- else
- $exec $PAGER $Opts "$@"
- fi
- }
-
- # Usage: fsub Old New String
- # Replaces each instance of string Old with string New in string String
- # The result is put in global fsub_ret
- function fsub {
- typeset Old=$1 New=$2 S=$3
- fsub_ret=
- # While the input string contains Old, peel off the part of the string
- # that comes before the first instance of Old, append it and New
- # to the output string, and remove the leading Old from the input string.
- while [ "${S%$Old*}" != "$S" ]; do
- fsub_ret="$fsub_ret${S%%$Old*}$New"
- # Get rid of the leading part of the string that contains old
- S=${S#*$Old}
- done
- fsub_ret="$fsub_ret$S" # Prepend the remaining part
- }
-
- # usage: pageComp <compressor>
- # If compressor has changed, page any compressed files that have been stored in
- # comp[]
- # A null argument is used for uncompressed files.
- function pageComp {
- # Page any compressed files that use any other uncompressor
- if [ "$1" != "$lastComp" ] && [ ${#comp[@]} -gt 0 ]; then
- [ -n "$lastComp" ] && export LESSOPEN="|exec $lastComp %s" ||
- unset LESSOPEN
- Page "" "$Opts" "${comp[@]}"
- unset comp[*]
- fi
- lastComp=$1
- }
-
- # Globals:
- # Returns match in CheckVer_ret
- # If version is not -1, it is taken to be a file version number.
- function CheckVer {
- typeset file=$1
-
- if [ version -eq 0 ]; then
- # undelete -l seems to list files in order of version, but the man
- # page doesn't claim that, so use sort to make sure
- undelete -l "$file" 2>/dev/null|sort -t\; -n +1 | read file || return 1
- elif [ version -ne -1 ]; then
- file="$file$vertail"
- fi
- if [ -r "$file" ]; then
- CheckVer_ret=$file
- return 0
- fi
- return 1
- }
-
- ### Start of main program
-
- DefPager=/usr/local/bin/less
-
- alias istrue="test 0 -ne"
- alias isfalse="test 0 -eq"
- stringsCmd=
- exec=
- Debug=false
- typeset -i version=-1
-
- name=${0##*/}
- Usage="Usage: $name [-hm] [-s<number>] [pager-option ...] [filename ...]"
-
- # Need leading : so getopts will not complain about unknown options.
- while getopts :hms:v: opt; do
- case $opt in
- h)
- print -r -- \
- "$name: page a file.
- $Usage
- Files are paged by the program specified in the user's PAGER
- environment variable, or by $DefPager if PAGER is not set.
- If no filename is given, text to page is read from the standard input.
- If filenames are given, they are either paged directly, or unpacked/
- uncompressed and then paged. Files are assumed to be in packed, compressed,
- gzipped, hzipped, or bzipped format if the filename ends in .Z, .z, .gz, .hz,
- or .bz respectively. If a filename that does not end in one of those
- extensions is given and is not found, it is searched for with each of those
- extensions attached.
- Each group of plain files is paged by a single instance of the pager.
- Each compressed file is paged by a separate instance of the pager.
- Options:
- -h: Print this help.
- -m: Convert carraige returns to newlines.
- -s<number>: Each file is passed through \"strings -a -<number>\". Each file is
- paged individually.
- -v<number>: Read version <number> of each file. This is equivalent to reading
- the file named filename;<number>. If 0 is given, the lowest-numbered
- file version that exists is read. If there is no versioned copy of the
- file, an error is produced (-v0 does not extend to the 0th version).
- Any other initial arguments beginning with + or - are taken to be pager options
- and are passed to each instance of the pager. If a pager option takes a value
- it should be given with the option as a single argument (with no space between
- the option and the value)."
- exit 0
- ;;
- m)
- [ -n "$stringsCmd" ] && stringsCmd="$stringsCmd |"
- stringsCmd="$stringsCmd tr '\015' '\012'"
- ;;
- s)
- [ -n "$stringsCmd" ] && stringsCmd="$stringsCmd |"
- stringsCmd="$stringsCmd strings -a -$OPTARG"
- ;;
- v)
- export SHOWVERSIONS=1
- version=$OPTARG || exit 1
- vertail=";$version"
- ;;
- :)
- print -r -u2 -- \
- "$name: Option '$OPTARG' requires a value. Use -h for help."
- exit 1
- ;;
- ?)
- break; # pager option
- esac
- done
-
- # remove args that were options
- let OPTIND=OPTIND-1
- shift $OPTIND
-
- # Get pager options
- while [[ "$1" = [-+]* ]]; do
- Opts="$Opts $1"
- shift
- done
-
- [ -z "$PAGER" ] && PAGER=$DefPager
-
- [[ "$PAGER" = *less ]] && useLO=true || useLO=false
-
- # Read from stdin
- if [ $# = 0 ]; then
- exec=exec
- Page "" "$Opts"
- fi
-
- typeset -i filenum=0 badfile=0
-
- # Verify/convert filenames
- for file; do
- if CheckVer "$file"; then
- file=$CheckVer_ret
- elif [[ "$file" != *.@([zZ]|[gbh]z) ]]; then
- # If file does not already have a compression extension, check whether
- # user specified a compressed file without giving its extension
- for ext in Z z gz bz hz; do
- if CheckVer "$file.$ext"; then
- file=$CheckVer_ret
- break
- fi
- done
- fi
- if [ ! -r "$file" ]; then
- print -u2 -- "$file$vertail: cannot read."
- badfile=1
- else
- files[filenum]=$file
- let filenum+=1
- fi
- done
-
- if istrue badfile && [ filenum -gt 0 ]; then
- print -u2 -n "Press return to continue..."
- read
- fi
-
- unset plain
-
- # Page files!
- lastComp=
- for file in "${files[@]}"; do
- # Get name of uncompressor
- case "$file" in
- *.@([zZ]|[gbh]z) )
- # one of these is guaranteed to work, due to the pattern test above
- set -- Z zcat z pcat gz gzcat bz "bzip -dc" hz "hzip -dc"
- while [ $# -gt 0 ]; do
- [[ "$file" = *.* && "${file##*.}" = "$1" ]] && break
- shift 2
- done
- ;;
- *) # no compressor
- set --
- ;;
- esac
- # Page any compressed files that use any other uncompressor
- pageComp "$2"
- # If an uncompressed file or we're using less (and so can page multiple
- # compressed files with a single instance of the pager), store filename.
- # Otherwise, uncompress & page it immediately.
- if $useLO || [ -z "$2" ]; then
- comp[${#comp[@]}]=$file
- else
- $2 "$file" | Page "$file" "$Opts"
- fi
- done
-
- # Page any files that haven't been paged yet
- exec=exec
- pageComp "foo" # to not match any uncompressor
-